Skip to content
On this page

复杂数据图表 · 关系图谱


第 14 节 复杂数据图表 · 关系图谱

关系图谱可以说是笔者我最喜欢的一种数据图表了,因为从很多年前的好莱坞科幻电影开始,主人公都会在一个悬浮在半空中的操作界面中进行操作。其中最具酷炫感的便是不同的球形之间通过一条线进行连接,操作者点击其中一个球体便会带动其他相连的球体,这简直太酷了。

还记得我们在第 8 节中所学习过的关系图谱数据结构吗?我们可以将其应用起来,变成一个非常酷炫的关系图谱。

14.1 准备数据

我们再次使用在第 8 节中准备好的关系图谱数据,一个简单却能够包含大部分情况的图谱数据。

有向图

const vertices = [
  new Vertex(1, 'A'),
  new Vertex(2, 'B'),
  new Vertex(3, 'C'),
  new Vertex(4, 'D'),
  new Vertex(5, 'E')
]

const edges = [
  new DirectedEdge(1, 2, 1),
  new DirectedEdge(1, 3, 2),
  new DirectedEdge(2, 4, 1),
  new DirectedEdge(3, 4, 1),
  new DirectedEdge(1, 1, 3),
  new DirectedEdge(3, 5, 4),
  new DirectedEdge(4, 5, 5)
]

虽然我们在第 8 节中创建了如 VertexEdgeDirectedEdge 这样的类以方便进行关系图谱算法实现以及代码的理解,但 ECharts 的关系图谱图表则相对简单许多,并不需要使用到特定的类进行内容的标识,只需准备好符合规则结构的数据即可。

对应上面的关系图谱数据,我们可以编写出以下数据集。

const vertices = [
  { name: 'A' },
  { name: 'B' },
  { name: 'C' },
  { name: 'D' },
  { name: 'E' }
]

const edges = [
  { source: 'A', target: 'B' },
  { source: 'A', target: 'C' },
  { source: 'B', target: 'D' },
  { source: 'C', target: 'D' },
  { source: 'A', target: 'A' },
  { source: 'C', target: 'E' },
  { source: 'D', target: 'E' }
]

比较特殊的是,因为关系图谱数据系列同时需要使用到两个数据集,所以没办法使用前面学习到的 datasetencode 来进行数据绑定。

14.2 关系图谱数据系列

在将数据集应用到数据图表中之前,首先我们需要了解的是虽然 ECharts 中的关系图谱图表也是建立在二维空间中的,但其与前面学习过的饼图类似,默认情况下并不需要使用到直角坐标系。

所以关系图谱中的每一个节点在二维空间中的位置是需要特定标明的,也就是每一个节点(Node)都需要带有二维空间的坐标信息(xy)。但显然这个任务由我们来完成并不现实,所以 ECharts 提供了几个比较实用的“模板”(Layout),以便于将关系图谱以比较好的形式展示在图表上。

  • Circular 环形,整个关系图谱的节点会围绕成一个环形结构,并根据实际节点之间的关系进行排列;
  • Force 力引导,关系图谱的分布会根据节点之间连接的“能量”来尽可能保持边长的一致和尽可能少地出现交叉。

Les Miserables Circular

Les Miserables Force

从这两张图我们可以看出同一份关系图谱数据分别使用两种不同的展示方式,便有着区别非常大的展示效果。环形井然有序中透露着不少的科技感,而力引导虽然看似杂乱无章却处处透露着数学的魅力。两种不同的模板可以根据实际的需要进行合理的选择,以达到更好的展示效果。

当然 ECharts 也同样支持在数据集中录入每一个节点的位置参数,通常用于展示由其他软件生成的关系图谱数据。

14.2.1 编写配置

因为关系图谱在一般情况下都不需要使用到坐标系来进行辅助,所以我们只需要直接指定数据系列的类别为 graph 即可,并将我们的数据传入到数据系列中。

const option = {
  series: {
    type: 'graph',
  
    // Dataset
    data: vertices,
    links: edges
  }
}

然后我们以环形模板为例子,以展示一个较为简单的关系图谱,只需要添加一个 layout 配置即可。

const option = {
  series: {
    // ...
    layout: 'circular'
  }
}

graph-chart-1

14.2.2 润色图表

看完前面章节的同学肯定都知道我们在绘制图表的时候都是采用循序渐进的形式进行绘制的,在完成了最基础的图表绘制以后,需要逐步地根据实际需求对图表进行优化润色。

在这个关系图谱中我们可以总结出以下需要优化的地方:

  1. 节点图标大小需要调整,目前的节点图标过小而导致画面空洞,当然这也跟节点数量有关;
  2. 有向边没有直观的标识,我们在准备节点之间的边时便已经标明了这些边均为有向边,而目前在图表上边的有向性并没有表现出来;
  3. 节点的名称没有标明。

节点大小

我们也是逐个将上面的问题进行解决,首先就是需要调整节点的大小,一般情况下只需要填写一个合适的大小即可。

const option = {
  series: {
    // ...
    symbolSize: 50
  }
}

graph-chart-2

展示标签

回想一下我们前面学习过的数据图表,当我们需要在数据系列上进行标签展示的时候需要添加什么配置?

const option = {
  series: {
    // ...
    label: {
      normal: {
        show: true
      }
    }
  }
}

graph-chart-3

展示有向边

因为在进行图表展示的时候,有向图的意义与无向图有着非常大的差别,而准确地表达数据集所包含的内容则是可视化工程的首要原则。

const option = {
  series: {
    type: 'graph',
    layout: 'circular',
    symbolSize: 50,
  
    // Dataset
    data: vertices,
    links: edges,
    
    label: {
      normal: {
        show: true
      }
    },
    
    edgeSymbol: [ 'circle', 'arrow' ],
    edgeSymbolSize: [ 4, 10 ]
  }
}

graph-chart-4

14.2.3 力引导关系图谱

前面我们使用了环形模板来展示我们的关系图谱数据,而 ECharts 还提供了力引导模板以供使用。力引导模板运用了一系列的数学原则以及算法来计算每一个节点的位置和节点之间的距离,综合得到最终的完整关系图谱。

将前面的环形配置更换为力引导 force

const option = {
  series: {
    // ...
    layout: 'force'
  }
}

graph-chart-5

咦?为什么更换了力引导模板以后整个关系图谱的节点都挤在了一起?因为我们前面设置的节点图标大小与力引导模板默认的大小相差太大,而在距离的计算上也并没有自动地进行适应,所以就出现了全部节点挤在了一起的现象。

为了修复这一问题,我们还需要对力引导模板进行配置,比如力引导中模板中节点之间的斥力大小以及边长的取值范围。

const option = {
  series: {
    // ...
    force: {
      repulsion: 100,
      edgeLength: [ 100, 500 ]
    }
  }
}

graph-chart-6

小结

这一节我们学习到了,如何将我们在第 8 节中学习到的关系图谱数据使用直观的图表展示出来,虽然图表并不能像图论算法一样通过计算节点之间的关系以进行动态调整,但却能更直观地将数据表达出来。